package model

import (
	"app/common/constant"
	"app/common/customtype"
	"app/common/funcs"
	"app/common/params"
	"app/common/response"
	"app/common/validation"
	"app/pkg/db"
	"app/pkg/log"
	"errors"
	"fmt"
	"math"
	"strings"
	"time"

	"github.com/shopspring/decimal"
	"gorm.io/gorm"
)

const (
	USER_STATE_NORMAL    = 1 //正常
	USER_STATE_FORBIDDEN = 2 //恶意操作禁用
	USER_STATE_ZHUXIAO   = 3 //注销
)

const (
	_               = iota
	USER_ROLE_ADMIN //超级管理员
)

type UserModel struct {
	CommonStruct
	Username string `gorm:"column:username;" json:"username"`
	PassSalt string `gorm:"column:pass_salt;" json:"passSalt"`
	Password string `gorm:"column:password;" json:"password"`
	Email    string `gorm:"column:email;" json:"email"`
	Phone    string `gorm:"column:phone;" json:"phone"`
	Openid   string `gorm:"column:openid" json:"openid"`
	Avatar   string `gorm:"column:avatar" json:"avatar"` //头像
	// PayPass       string               `gorm:"column:pay_pass;" json:"PayPass"`
	Sex           int8                 `gorm:"column:sex;" json:"sex"`     //1 男 2女 3未知
	State         int8                 `gorm:"column:state;" json:"state"` //1 正常 2禁用 3注销
	LastLoginIp   string               `gorm:"column:last_login_ip;" json:"lastLoginIp"`
	LastLoginTime customtype.LocalTime `gorm:"column:last_login_time;" json:"lastLoginTime"`
	Beans         decimal.Decimal      `gorm:"column:beans" json:"beans"`            //积分
	Type          int8                 `gorm:"column:type" json:"type"`              //用户类型 1普通会员 2管理员
	InviteCode    string               `gorm:"column:invite_code" json:"inviteCode"` //邀请码
	Credit        int                  `gorm:"column:credit" json:"credit"`          //信用分
}

type UserBaseResponse struct {
	CommonStruct
	State    int8    `gorm:"column:state;" json:"state"` //1 正常 2禁用
	Username string  `json:"username"`
	Beans    float64 `gorm:"column:beans" json:"beans"`   //积分
	Avatar   string  `gorm:"column:avatar" json:"avatar"` //头像
}

type UserLoginReply struct {
	// Username string              `json:"username"`                    //用户名
	Beans  decimal.Decimal     `gorm:"column:beans" json:"beans"`   //积分
	Sign   string              `json:"sign"`                        //登录凭证
	Avatar string              `gorm:"column:avatar" json:"avatar"` //头像
	Id     customtype.IdString `json:"id"`                          //加密的id
	Type   int8                `json:"type"`                        // 1普通会员 2管理员
}

func NewUserModel() *UserModel         { return &UserModel{} }
func (m *UserModel) TableName() string { return "user" }

func (m *UserModel) WxRegister() error {
	dbConn, err := db.DB.MysqlDB.DefaultGormDB()
	if err != nil {
		return err
	}
	m.Type = 1
	m.State = 1
	m.Sex = 3
	return dbConn.Omit("create_time", "update_time", "last_login_time").Table("user").Create(&m).Error
}

func (m *UserModel) Register(dbConn *gorm.DB, r *UserModel) error {
	r.Username = strings.TrimSpace(r.Username)
	if r.Username == "" {
		return fmt.Errorf("用户名不能为空")
	}
	if r.Password == "" {
		return fmt.Errorf("请设置密码")
	}
	if !validation.MobileValidator(r.Phone) {
		return fmt.Errorf("手机号格式错误")
	}
	if existed, _ := FindOne[UserModel](map[string]interface{}{"username": r.Username}); existed.Id > 0 {
		return errors.New("用户名已存在")
	}
	salt := funcs.GenRandomString(32)
	secret := funcs.EncryptLoginPass(r.Password, salt)
	r.Password = secret
	r.PassSalt = salt
	return dbConn.Omit("create_time", "update_time", "last_login_time").Table("user").Create(&r).Error
}

func (m *UserModel) UpdateLoginInfo(uid int64, last_login_ip string, last_login_time string) {
	dbConn, err := db.DB.MysqlDB.DefaultGormDB()
	if err == nil {
		dbConn.Model(m).Where("id = ?", uid).
			Updates(map[string]interface{}{
				"last_login_ip":   last_login_ip,
				"last_login_time": last_login_time,
			})
	}
}

type ParamsSearchUser struct {
	Key string `json:"key" form:"key" validate:"required"`
}

func (m *UserModel) UserProfile(uid int64, username string, desc string, faceUrl string) error {
	conn, err := db.DB.MysqlDB.DefaultGormDB()
	if err != nil {
		return err
	}
	update := make(map[string]interface{})
	if username != "" {
		var count int64
		conn.Table("user").Where("username = ? AND id != ?", username, uid).Count(&count)
		if count > 0 {
			return errors.New("用户名已存在")
		}
		update["username"] = username
	}

	if faceUrl != "" {
		update["face_url"] = faceUrl
	}
	if desc != "" {
		update["desc"] = desc
	}
	if len(update) <= 0 {
		return nil
	}
	update["updated_at"] = time.Now().Unix()
	return conn.Table("user").Where("id = ?", uid).Updates(update).Error
}

func UserIndex(age, gender int, pgParams params.ParamsPagination) (users []UserModel, paginate response.Paginate, err error) {
	paginate.Limit = pgParams.Limit
	paginate.Page = pgParams.Page
	conn, err := db.DB.MysqlDB.DefaultGormDB()
	if err != nil {
		return
	}
	conditionRst := func() func(db *gorm.DB) *gorm.DB {
		return func(db *gorm.DB) *gorm.DB {
			if gender > 0 {
				db.Where("gender = ?", gender)
			}
			return db
		}
	}()
	err = conn.Table("user").Scopes(PaginateScope(pgParams.Page, pgParams.Limit), UserNormalScope("state"), conditionRst).Order("id desc").Find(&users).Error
	if err == nil {
		var count int64
		err = conn.Table("user").Scopes(UserNormalScope("state"), conditionRst).Count(&count).Error
		if err == nil {
			paginate.Total = count
			total := float64(count) / float64(int64(pgParams.Limit))
			paginate.Pages = int(math.Ceil(total))
		}
	}
	return
}

func (m *UserModel) UpdatePasswd(passwd, passSalt string, uid int64) (err error) {
	conn, err := db.DB.MysqlDB.DefaultGormDB()
	if err != nil {
		return
	}
	secret := funcs.EncryptLoginPass(passwd, passSalt)
	return conn.Table("user").Where("id = ?", uid).Updates(map[string]interface{}{"password": secret, "updated_at": time.Now().Unix()}).Error
}

func SwitchPhone(requestId string, phone string, uid int64) (err error) {
	conn, err := db.DB.MysqlDB.DefaultGormDB()
	if err != nil {
		log.NewError(requestId, "db conn error ", err)
		return errors.New("服务器错误")
	}
	//判断手机号是否被占用
	var count int64
	err = conn.Table("user").Where("phone = ?", phone).Count(&count).Error
	if count >= 1 {
		err = errors.New("手机号已被注册")
		return
	}
	if err != nil {
		log.NewError(requestId, "db error ", err)
		return
	}
	var user map[string]interface{}
	result := conn.Table("user").Select("state", "id", "phone").Where("id = ?", uid).Take(&user)
	err = result.Error
	if err != nil {
		log.NewError(requestId, "db error ", err)
		return
	}
	if result.RowsAffected != 1 {
		err = errors.New("账号不存在")
		return
	}
	state := user["state"].(int64)
	if state >= 2 {
		err = errors.New("账号异常,请联系客服")
		return
	}
	if user["phone"] == phone {
		err = errors.New("手机号未改变")
		return
	}
	//修改手机号
	err = conn.Table("user").Where("id = ?", uid).Update("phone", phone).Error
	return
}

// 设置支付密码
func (m *UserModel) SetPayPwd(db *gorm.DB, userId int64, pwd string) (bool, error) {
	var model UserModel
	db.Model(&m).Where("id=?", userId).Select("pay_pass,id").Take(&model)
	if model.Id == 0 {
		return false, nil
	}
	if res := db.Model(&model).Update("pay_pass", funcs.Sha256(pwd)); res.Error != nil {
		return false, res.Error
	}
	return true, nil
}

// 检查支付密码
func (m *UserModel) CheckPayPwd(userId int64, pwd, originPwd string) error {
	if originPwd == "" {
		dbConn, err := db.DB.MysqlDB.DefaultGormDB()
		if err != nil {
			return errors.New(constant.ErrServer.Msg)
		}
		var temp UserModel
		result := dbConn.Model(&m).Where("id=?", userId).Select("pay_pass").Take(&temp)
		if result.RowsAffected == 0 {
			return errors.New("用户数据错误")
		}
		// originPwd = temp.PayPass
	}
	if originPwd == "" {
		return errors.New("未设置支付密码")
	}
	if originPwd != funcs.Sha256(pwd) {
		return errors.New("支付密码输入错误")
	}
	return nil
}

func (m *UserModel) LoginVerify(user UserModel, password string) (err error) {
	if user.State == 2 {
		err = errors.New("账号已被禁用")
		return
	}
	if password != "" {
		if user.Password != funcs.EncryptLoginPass(user.Password, user.PassSalt) {
			err = errors.New("密码输入错误")
			return
		}
	}
	return
}
